package com.xpec.canaan.util;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ExecutorService;

public class CompareUnderDirectory {
	
	public CompareUnderDirectory(String originalBasePath, String newBasePath, String filterName, TestCompareFile mainThread)
	{
		m_originalBasePath = originalBasePath;
		m_newBasePath = newBasePath;
		m_filterName = filterName;
		m_mainThread = mainThread;
	}
	
	public void startCompare(ExecutorService pools) throws IOException
	{
		m_totalCount = 0;
		
		File orgDirFile = new File(m_originalBasePath);
		File currDirFile = new File(m_newBasePath);
		// dirs under input directory
		ArrayList<String> dirNames = new ArrayList<String>();
		ArrayList<String> subFiles = new ArrayList<String>();
		
		parserDirName(orgDirFile, dirNames, subFiles);
		if( 0 == dirNames.size() )
		{
			parserDirName(currDirFile, dirNames, subFiles);
		}
		
		if( 0 == dirNames.size() )
		{
			//does not exist any directory 
			throw new IOException("does not exist any directory under: " + m_originalBasePath + " and " + m_newBasePath);
		}
		
		m_results = new Hashtable<String,CompareResultRecorder>();
		// files under input directory
		if( 0 != subFiles.size() )
		{
			m_totalCount += 1;
		}
		
		m_totalCount += dirNames.size();
		m_CompleteCount = 0;
		
		if( 0 != subFiles.size() )
		{
			CompareSingleDirectoryRecorder underFile = new CompareSingleDirectoryRecorder(m_originalBasePath, m_newBasePath, subFiles.get(0), this);
			pools.execute(underFile);
		}
		for(int i = 0; i < dirNames.size(); i++)
		{
			File file = new File(m_originalBasePath + "//" + dirNames.get(i));
			File relatedFile = new File(m_newBasePath + "//" + dirNames.get(i));
			if( relatedFile.exists() )
			{
				CompareSingleDirectoryRecorder recorder = new CompareSingleDirectoryRecorder(file.getAbsolutePath(), relatedFile.getAbsolutePath(), dirNames.get(i), this);
				pools.execute(recorder);
			}
		}
	}
	
	private boolean parserDirName(File baseDir, ArrayList<String> parserDirs, ArrayList<String> existsFiles)
	{
		if( null == parserDirs || null == existsFiles)
		{
			return false;
		}
		
		File[] allDir = null;
		if( null == m_filterName )
		{
			allDir = baseDir.listFiles(); 
		}
		else
		{
			allDir = baseDir.listFiles(new MyFileNameFilter(m_filterName));
		}
		
		if( null != allDir )
		{
			for( int i = 0; i < allDir.length; i++ )
			{
				if( allDir[i].isDirectory())
				{
					parserDirs.add(allDir[i].getName());
				}
				else if(allDir[i].isFile() )
				{
					String fileName = allDir[i].getName();
					if( fileName.equals(CompareResultRecorder.CompareFileName))
					{
						existsFiles.add(allDir[i].getName());
					}
				}
			}
		}
		return true;
	}
	
	public synchronized void addCompareResult(CompareResultRecorder result)
	{
		m_results.put(result.getName(), result);
		m_CompleteCount++;
		if(m_CompleteCount == m_totalCount)
		{
			Set<String> orset = m_results.keySet();
			Iterator<String> oritr = orset.iterator();
			while( oritr.hasNext() )
			{
				String key = oritr.next();
				CompareResultRecorder tempResult = m_results.get(key);
				System.out.println(tempResult.getName() + " test result is: " + tempResult.getIsEquals());
			}
			
			// TODO tell main thread work complete
			System.out.println("Compare Finished");
			File completePath = new File(m_originalBasePath);
			m_mainThread.notifyCompareFinished(completePath.getName(), m_results);
		}
	}
	
	class MyFileNameFilter implements FilenameFilter
	{
		public MyFileNameFilter(String filtername)
		{
			m_filterName = filtername;
		}
		
		public boolean accept(File dir, String name )
		{
			return !isContainName(name);
		}
		
		public boolean isContainName(String file)
		{
			return file.contains(m_filterName);
		}
		
		private String m_filterName;
	}
	
	private String m_filterName;
	private String m_originalBasePath;
	private String m_newBasePath;
	private int m_totalCount;
	private int m_CompleteCount;
	private TestCompareFile m_mainThread;
	Hashtable<String,CompareResultRecorder> m_results;
}
